#include "ncis.h"
#include "../log/log.h"
#include <string.h>
#include <math.h>
#include <ctype.h>

int
NCIS_get_ncis_type(const char * command,size_t commandlen)
{

 int ret = 0;
 char * commandsav = (char *) malloc(sizeof(char)*commandlen);
 if(!commandsav){
 	//LOG_add(LOG_ERROR, "NCIS_get_ncis_type: cannot alloc memory");
	ret = -1;
 }

 memcpy(commandsav,command,commandlen);
	
 strtok(commandsav," ");

 if(strcmp(commandsav,"list")==0){
	///List command processing
	ret = NCIS_LIST;

	}
 else if(strcmp(commandsav,"file")==0){
	///File command processing
	ret = NCIS_FILE;
 }	
 else if(strcmp(commandsav,"get")==0){
	///Get command processing
	ret = NCIS_GET;
 	}
 else if(strcmp(commandsav,"traffic")==0){
	///Traffic command processing
	ret = NCIS_TRAFFIC;
 	}
 else if(strcmp(commandsav,"ready")==0){
	///Ready command processing
	ret = NCIS_READY;
 	}
 else if(strcmp(commandsav,"checksum")==0){
	///Checksum command processing
	ret = NCIS_CHECKSUM;
 	}
 else if(strcmp(commandsav,"info")==0){
	///Info command processing
	ret = NCIS_INFO;
 	}
 else if(strcmp(commandsav,"neighbourhood")==0){
	///Neighbourhood command processing
	ret = NCIS_NEIGHBOURHOOD;
 	}
 else if(strcmp(commandsav,"neighbour")==0){
	///Neighbour command processing
	ret = NCIS_NEIGHBOUR;
 	}
 else if(strcmp(commandsav,"redirect")==0){
	///Redirect command processing
	ret = NCIS_REDIRECT;
 	}
 else if(strcmp(commandsav,"error")==0){
	///Error command processing
	ret = NCIS_ERROR;
 	}
 else{
	///Error
	ret = -1;
 }

  free(commandsav);
  return ret;

}


int
NCIS_fprintf(FILE * stream, const ncis_standard_s * ncis)
{
 int ret;
 if(!ncis){
 	///error
 	return -1;
 }

 switch(ncis->type){
 	case NCIS_LIST:
		ret = fprintf(stream,"packet type : list\n");
		break;
	case NCIS_FILE:
		ret = fprintf(stream,"packet type : file\nfilename : %s\nkey : %.32s\nsize : %ld\nip : %d.%d.%d.%d\nport : %d\n",
		ncis->file.filename,ncis->file.key,ncis->file.size,
		ncis->file.ip[0],ncis->file.ip[1],ncis->file.ip[2],ncis->file.ip[3],
		ncis->file.port);
		break;
	case NCIS_GET:
		ret = fprintf(stream,"packet type : get\n key : %.32s\nbegin : %ld\nend : %ld\n",
		ncis->get.key,ncis->get.begin,ncis->get.end);
		break;
	case NCIS_TRAFFIC:
		ret = fprintf(stream,"packet type : traffic\n");
		break;
	case NCIS_READY:
		ret = fprintf(stream,"packet type : ready\nkey : %.32s\ndelay : %d\nip : %d.%d.%d.%d\nport : %d\nproto : %d\nbegin : %ld\nend : %ld\n",
		ncis->ready.key,ncis->ready.delay,
		ncis->ready.ip[0],ncis->ready.ip[1],ncis->ready.ip[2],ncis->ready.ip[3],
		ncis->ready.port,ncis->ready.proto,ncis->ready.begin,ncis->ready.end);
		break;
	case NCIS_CHECKSUM:
	case NCIS_CHECKSUM_LAST:
		ret = fprintf(stream,"packet type : checksum\nkey : %.32s\nblock size : %ld\nbegin : %ld\nchecksum : %.32s\n",
		ncis->checksum.key,ncis->checksum.block_size,ncis->checksum.begin,ncis->checksum.checksum);
		break;
	case NCIS_INFO:
		ret = fprintf(stream,"packet type : info\n");
		break;
	case NCIS_NEIGHBOURHOOD:
		ret = fprintf(stream,"packet type : neighbourhood\n");
		break;
	case NCIS_NEIGHBOUR:
		ret = fprintf(stream,"packet type : neighbour\nip : %d.%d.%d.%d\nport : %d\n",
		ncis->neighbour.ip[0],ncis->neighbour.ip[1],ncis->neighbour.ip[2],ncis->neighbour.ip[3],ncis->neighbour.port);
		break;
	case NCIS_REDIRECT:
		ret = fprintf(stream,"packet type : redirect\nkey : %.32s\nip : %d.%d.%d.%d\nport : %d\n",
		ncis->redirect.key,ncis->redirect.ip[0],ncis->redirect.ip[1],ncis->redirect.ip[2],ncis->redirect.ip[3],ncis->redirect.port);
	case NCIS_ERROR:
		ret = fprintf(stream,"packet type : error\ntype : %d\nmessage %s\n",
		ncis->error.ncis_type,ncis->error.message);
	default :
		ret = -1;
		break;
	}

	return ret;

}


int 
NCIS_get_key(filekey_t key,char * data)
{
  int i;
  int ret = 0;
  char * dataptr ;
  dataptr = data;
  for(i=0;i<32;i++){
  	if(isxdigit((int)*dataptr)){
  		key[i]=*dataptr;	
		dataptr++;
	}
	else{
		ret = -1;
		break;
	}
  }
  return ret;
}
	


int
NCIS_np2ncis(CLNode_s * ncis_root, npacket_s *np)
{

 int ret = 0;
 int tmp;
 ncis_standard_s * ncis = (ncis_standard_s *)malloc(sizeof(ncis_standard_s));
 char * data = (char *)OSOCK_get_npacket_data(np);
 size_t datalen = OSOCK_get_npacket_length(np);
 int end_filename = 0;
 char * dataptr;
 char * datasav;
 int write_data;
 int read_data;
 int i;
 //usefull for checksum
 CLNode_s * ncis_root_tmp;
 CLNode_s * node_tmp;
 filekey_t key;
 unsigned int block_size;
 off_t begin;
 off_t end;
 int n_checksum;


 switch(NCIS_get_ncis_type(data,datalen)){

 	case NCIS_LIST :
		///List command processing
		ncis->type=NCIS_LIST;
		///no process option
		ret = 0;
		break;
	
	case NCIS_FILE :
		///File command processing
		ncis->type=NCIS_FILE;
		///get file name
		if ( *(data+5) != '"'){
			ret = -2;
			break;
		}
		dataptr = data+6;
		datasav = ncis->file.filename;
		read_data = 6;
		write_data = 0;
		while(!end_filename && read_data<datalen && write_data<FILENAME_MAX){
			switch(*dataptr){
				case '\\' :
					*datasav = *(dataptr+1);
					datasav++;
					dataptr += 2;
					read_data += 2;
					write_data++;
					break;
				case '"' :
					*datasav='\0';
					end_filename = 1;
					dataptr ++;
					break;
				default :
					*datasav = *dataptr;
					datasav++;
					dataptr++;
					read_data++;
					write_data++;
					break;
			}
		}
		if(!end_filename){
			*datasav='\0';
			ret=-1;
			break;
		}
		if(*dataptr!=' '){
			ret = -1;
			break;
		}
		dataptr++;
		///get filekey
		tmp = NCIS_get_key(ncis->file.key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr += 33;
		///get size
		ncis->file.size = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!=' '){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		///get ip
		ncis->file.ip[0] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->file.ip[1] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->file.ip[2] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->file.ip[3] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!=':'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		
		///get port
		ncis->file.port = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data > datalen ){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		ret = 0;
		break;
 	
	case NCIS_GET :
		///Get command processing
		ncis->type=NCIS_GET;
		
		dataptr = data+4;
		read_data = 4;

		///get filekey
		tmp = NCIS_get_key(ncis->get.key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr += 33;

		///get begin
		ncis->get.begin = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		///get end
		ncis->get.end = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		ret = 0;
		break;

	case NCIS_TRAFFIC :
		///Traffic command processing
		ncis->type=NCIS_TRAFFIC;
		ret = 0;
 		break;

	case NCIS_READY :
		///Ready command processing
		ncis->type=NCIS_READY;
		dataptr = data+6;
		read_data = 6;

		///get filekey
		tmp = NCIS_get_key(ncis->ready.key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr += 33;

		///get delay
		ncis->ready.delay = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		///get ip
		ncis->ready.ip[0] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->ready.ip[1] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->ready.ip[2] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->ready.ip[3] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!=':'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		
		///get port
		ncis->ready.port = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data > datalen || *datasav!=' ' ){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		/// get proto
		if(strncmp(dataptr,"udp ",4)==0){
			ncis->ready.proto=NCIS_PROTO_UDP;
			dataptr += 4;
		}
		else if(strncmp(dataptr,"tcp ",4)==0){
			ncis->ready.proto=NCIS_PROTO_TCP;
			dataptr += 4;
		}
		else{
			ret = -1;
			break;
		}
	
		///get begin
		ncis->ready.begin = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			break;
		}
		dataptr=datasav+1;


		///get end
		ncis->ready.end = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		ret = 0;
	
 		break;

	case NCIS_CHECKSUM :
		///Checksum command processing
		//ncis->type=NCIS_CHECKSUM;
		ncis_root_tmp =  CL_create();
		dataptr = data+9;
		read_data = 9;

		///get filekey
		tmp = NCIS_get_key(key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr +=33;
	
		///get block_size
		block_size = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			//LOG_add(LOG_DEBUG, "NCIS_np2ncis: packet checksum bad bloc_size");
			break;
		}
		dataptr=datasav+1;

		///get begin
		begin = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			//LOG_add(LOG_DEBUG, "NCIS_np2ncis: packet checksum bad begin");
			break;
		}
		dataptr=datasav+1;

		///get end
		end = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav != ' '){
			ret = -1;
			//LOG_add(LOG_DEBUG, "NCIS_np2ncis: packet checksum bad end");
			break;
		}
		dataptr=datasav+1;

		/// number of checksum
		n_checksum = ceil(((double)end-begin)/(double)block_size);

		for(i=0;i<n_checksum-1;i++)
		{
			tmp = NCIS_get_key(ncis->checksum.checksum,dataptr);
			if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
				ret = -1;
				break;
			}
			dataptr +=33;
			ncis->type = NCIS_CHECKSUM;
			ncis->checksum.begin = begin;
			begin +=  block_size;
			ncis->checksum.block_size = block_size;
			memcpy(ncis->checksum.key,key,sizeof(filekey_t));
			CL_push_back(ncis_root_tmp,(void *)ncis);
			ncis = (ncis_standard_s *) malloc(sizeof(ncis_standard_s));
		}
		if(ret!=-1){ 
			///add the last checksumi
			tmp = NCIS_get_key(ncis->checksum.checksum,dataptr);
			if(tmp<0){
				ret = -1;
				break;
			}
			else{
			ncis->type = NCIS_CHECKSUM_LAST;
			ncis->checksum.begin = begin;
			ncis->checksum.block_size = end-begin;
			memcpy(ncis->checksum.key,key,sizeof(filekey_t));
			CL_push_back(ncis_root_tmp,(void *)ncis);
			}
		}
		if(ret==-1){
			//free
			CL_map(ncis_root_tmp,free);
		}
		else{
			//cat ncis_root_tmp to ncis_root
			node_tmp = CL_first(ncis_root_tmp);
			while(node_tmp){
				CL_push_back(ncis_root,node_tmp->data);
				CL_remove(node_tmp);
				node_tmp = CL_first(ncis_root_tmp);
			}
			ret = 1;
		}
		CL_destroy(ncis_root_tmp);
 		break;

	case NCIS_INFO :
		///Info command processing
		ncis->type=NCIS_INFO;
		
		dataptr = data+5;
		read_data = 5;

		///get filekey
		tmp = NCIS_get_key(ncis->info.key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr += 33;

		ret = 0;
 		break;
	
	case NCIS_NEIGHBOURHOOD :
		///Neighbourhood command processing
		ncis->type=NCIS_NEIGHBOURHOOD;
		ret = 0;
 		break;

	case NCIS_NEIGHBOUR :
		///Neighbour command processing
		ncis->type=NCIS_NEIGHBOUR;
 		dataptr = data+10;
		read_data = 10;
		
		///get ip
		ncis->neighbour.ip[0] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->neighbour.ip[1] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->neighbour.ip[2] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->neighbour.ip[3] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!=':'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		
		///get port
		ncis->neighbour.port = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data > datalen){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ret = 0;
		
		break;

	case NCIS_REDIRECT : 
		///Redirect command processing
		ncis->type=NCIS_REDIRECT;
 		dataptr = data+9;
		read_data = 9;
	
		///get filekey
		tmp = NCIS_get_key(ncis->redirect.key,dataptr);
		if(tmp<0 || read_data+32 >= datalen || *(dataptr+32) != ' '){
			ret = -1;
			break;
		}
		dataptr += 33;


		///get ip
		ncis->redirect.ip[0] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->redirect.ip[1] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->redirect.ip[2] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!='.'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		ncis->redirect.ip[3] = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data >= datalen || *datasav!=':'){
			ret = -1;
			break;
		}
		dataptr=datasav+1;
		
		///get port
		ncis->redirect.port = strtol(dataptr,&datasav,0);
		read_data += datasav-dataptr+1;
		if(datasav==dataptr || read_data > datalen || *datasav!=' ' ){
			ret = -1;
			break;
		}
		dataptr=datasav+1;

		ret = 0;
 		break;

	case NCIS_ERROR :
		///Error command processing
		ncis->type=NCIS_ERROR;
		dataptr = data+5;
		read_data = 5;
		if (datalen>5)
		ncis->error.ncis_type=NCIS_get_ncis_type(data+5,datalen-5);
		if (ncis->error.ncis_type<0){
			//error
			ret = -1;
			break;
		}
		while(*dataptr!=' ' || read_data < datalen){
			dataptr ++;
			read_data++;
		}
		if(read_data>=datalen){
			ret = -1;
			break;
		}
		dataptr ++;
		//copy the rest of data in message in message field
		strncpy(ncis->error.message,dataptr,LENGTH_MAX_ERROR_MESSAGE);
		ret = 0;
		break;
 	
	default :
		///Error
		ret = -1;
		break;
	}

	if(ret==0){
		CL_push_back(ncis_root,(void *)ncis);
	}
	else if(ret<0){
		free(ncis);
	}
	return ret;
}


int
NCIS_ncis2np(npacket_s * np , CLNode_s * ncis_root)
{
	
	int ret;
	ncis_standard_s * ncis;
	char * data;

	if(!ncis_root){
		///Error
		return -1;
	}

	ncis = (ncis_standard_s *) (CL_first(ncis_root)->data);

	if(!ncis){
		///Error
		return -1;
	}

	switch(ncis->type){
		
		case NCIS_LIST:
			data = (char *) malloc(sizeof(char)*6);
			sprintf(data,"list\n");
			OSOCK_fill_npacket(np,(void *)data,6);
			ret = 0;
			break;

		case NCIS_FILE:
			data = (char *) malloc(sizeof(char)*4095); ///TODO find a better way to alloc just enough space
			/// TODO escape filename
			sprintf(data,"file \"%s\" %.32s %ld %d.%d.%d.%d:%d\n",
			ncis->file.filename,ncis->file.key,ncis->file.size,
			ncis->file.ip[0],ncis->file.ip[1],ncis->file.ip[2],
			ncis->file.ip[3],ncis->file.port);
			OSOCK_fill_npacket(np,(void *)data,4095);
			ret = 0;
			break;

		case NCIS_GET:
			data = (char *) malloc(sizeof(char)*4095);
			sprintf(data,"get %.32s %ld %ld\n",
			ncis->get.key,ncis->get.begin,ncis->get.end);
			OSOCK_fill_npacket(np,(void *)data,4095);
			ret = 0;
			break;
		case NCIS_TRAFFIC:
			data = (char *) malloc(sizeof(char)*9);
			sprintf(data,"traffic\n");
			OSOCK_fill_npacket(np,(void *)data,9);
			ret = 0;
			break;
		case NCIS_READY:
			data = (char *) malloc(sizeof(char)*4095);
			sprintf(data,"ready %.32s %d %d.%d.%d.%d:%d ",
			ncis->ready.key,ncis->ready.delay,
			ncis->ready.ip[0],ncis->ready.ip[1],
			ncis->ready.ip[2],ncis->ready.ip[3],
			ncis->ready.port);
			switch(ncis->ready.proto){
				case(NCIS_PROTO_UDP):
					strcat(data,"udp ");
					break;
				case(NCIS_PROTO_TCP):
					strcat(data,"tcp ");
					break;
				default:
					break;
			}
			sprintf(data+sizeof(data),"%ld %ld\n",
			ncis->ready.begin,ncis->ready.end);
			OSOCK_fill_npacket(np,(void *)data,4095);
			ret = 0;
			break;

				
		case NCIS_CHECKSUM:
			// not implement yet. The father have to send only one checksum each time
			ret = -1;
			break;
		case NCIS_CHECKSUM_LAST:
			data = (char *) malloc(sizeof(char)*4095);
			sprintf(data,"checksum %.32s %ld %ld %ld %.32s\n",
			ncis->checksum.key,ncis->checksum.block_size,
			ncis->checksum.begin,(long int)(ncis->checksum.begin
			+ncis->checksum.block_size),
			ncis->checksum.checksum);
			OSOCK_fill_npacket(np,(void *)data,4095);
			ret = 0;
			break;
		case NCIS_INFO:
			data = (char *) malloc(sizeof(char)*23);
			sprintf(data,"info %.32s\n",ncis->info.key);
			OSOCK_fill_npacket(np,(void *)data,23);
			ret = 0;
			break;
		case NCIS_NEIGHBOURHOOD:
			data = (char *) malloc(sizeof(char)*15);
			sprintf(data,"neighbourhood\n");
			OSOCK_fill_npacket(np,(void *)data,15);
			ret = 0;
			break;
		case NCIS_NEIGHBOUR:
			data = (char *) malloc(sizeof(char)*33);
			sprintf(data,"neighbour %d.%d.%d.%d:%d\n",
				ncis->neighbour.ip[0],ncis->neighbour.ip[1],ncis->neighbour.ip[2],ncis->neighbour.ip[3],ncis->neighbour.port);
			OSOCK_fill_npacket(np,(void *)data,33);
			ret = 0;
			break;	
		case NCIS_REDIRECT:
			data = (char *) malloc(sizeof(char)*48);
			sprintf(data,"redirect %.32s %d.%d.%d.%d:%d\n",
			ncis->redirect.key,ncis->redirect.ip[0],ncis->redirect.ip[1],ncis->redirect.ip[2],ncis->redirect.ip[3],ncis->redirect.port);
			OSOCK_fill_npacket(np,(void *)data,48);
			ret = 0;
			break;
		case NCIS_ERROR:
			data = (char *) malloc(sizeof(char)*4095);
			sprintf(data,"error ");
			switch(ncis->error.ncis_type){
				case(NCIS_LIST):
					strcat(data,"list ");
					break;
				case(NCIS_FILE):
					strcat(data,"file ");
					break;
				case(NCIS_GET):
					strcat(data,"get ");
					break;
				case(NCIS_TRAFFIC):
					strcat(data,"traffic");
					break;
				case(NCIS_READY):
					strcat(data,"ready ");
					break;
				case(NCIS_CHECKSUM):
				case(NCIS_CHECKSUM_LAST):
					strcat(data,"checksum ");
					break;
				case(NCIS_INFO):
					strcat(data,"info ");
					break;
				case(NCIS_NEIGHBOURHOOD):
					strcat(data,"neighbourhood ");
					break;
				case(NCIS_NEIGHBOUR):
					strcat(data,"neighbour ");
					break;
				case(NCIS_REDIRECT):
					strcat(data,"redirect ");
					break;
				case(NCIS_ERROR):
					strcat(data,"error ");
					break;
				default:
					break;
			}
			strcat(data,ncis->error.message);
			strcat(data,"\n");
			OSOCK_fill_npacket(np,(void *)data,4095);
			ret = 0;
			break;
		default :
			ret = -1;
			break;

	}

	return ret;

}


int
NCIS_launch(SM_elem_s * sm_ncis, SM_elem_s * sm_father, msd_s * socket)
{
	int i, ret;
	npacket_s np;
	char data_to_receive[MAX_NPACK_SIZE];
  	np.datap = (void*) &data_to_receive;
  	np.datalen = 0;

		
	ncis_standard_s * ncis;
	CLNode_s * ncis_root_from_father =  CL_create(); //use to read from father
	CLNode_s * ncis_root_to_father = CL_create(); //use to read to father
	CLNode_s * node_tmp;
	//connection
	OSOCK_validate_tcp_server(socket);
	((ncis_standard_s*)sm_ncis->data)->type = NCIS_CONNECTED;	
	sm_ncis->state=SM_FULL;

	while(1){

		//break;
		//Something to read from network
		ret = OSOCK_watch_connection(socket,5);
		if(ret==0)
		{
			i = OSOCK_receive(&np,socket);
			if(i<=0){
				LOG_add(LOG_DEBUG,"NCIS quit du to connection problem");
				break;
			}
		//TODO make a buffer to be sur to give a full command to NCIS_np2ncis
			if(i>0){
				ret = NCIS_np2ncis(ncis_root_to_father,&np);
				if(ret <0)
					LOG_add(LOG_DEBUG,"Error parsing packet");
				else
					NCIS_fprintf(stderr,(ncis_standard_s *)(CL_first(ncis_root_to_father)->data));
			}
		}
		//Something to write to network
		if(CL_first(ncis_root_from_father)){
			NCIS_ncis2np(&np,ncis_root_from_father);
			OSOCK_send(socket,&np);
		}

		//Something to read from father
		if(sm_father->state==SM_FULL ){
			LOG_add(LOG_DEBUG,"NCIS: I read something from daddy");
			ncis =(ncis_standard_s *) malloc(sizeof(ncis_standard_s));
			memcpy(ncis,sm_father->data,sizeof(ncis_standard_s));
			CL_push_back(ncis_root_from_father,(void *)ncis);
			sm_father->state=SM_EMPTY;
		}


		//Something to write to father
		if(sm_ncis->state==SM_EMPTY && CL_first(ncis_root_to_father)){
			LOG_add(LOG_DEBUG,"daddy something to read");
			node_tmp = CL_first(ncis_root_to_father);
			memcpy(sm_ncis->data,node_tmp->data,sizeof(ncis_standard_s));
			free(node_tmp->data);
			CL_remove(node_tmp);
			sm_ncis->state=SM_FULL;
		}
	}

	//free
	CL_map(ncis_root_from_father,free);
	CL_map(ncis_root_to_father,free);
	CL_destroy(ncis_root_from_father);
	CL_destroy(ncis_root_to_father);

	//deconnection
	OSOCK_disconnect(socket);

	return 0;
}


